package cn.com.zj.rpc.client;

import cn.com.zj.rpc.handler.MyRpcClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @ClassName MyRpcClient
 * @Description 自定义rpc客户端
 * 业务：
 * 1.连接netty服务端
 * 2.提供调用者主动关闭资源的方法
 * 3.提供向服务端发送消息的方法
 * @Author ZikZ227412
 * @DATE 2021/12/9 15:01
 * @Version 1.0
 */
public class MyRpcClient {

    private String ip;

    private Integer port;

    private NioEventLoopGroup nioEventLoopGroup;

    private Channel channel;

    private MyRpcClientHandler myRpcClientHandler = new MyRpcClientHandler();

    private ExecutorService executorService = Executors.newCachedThreadPool();

    public MyRpcClient(String ip, Integer port) {
        this.ip = ip;
        this.port = port;
        init();
    }

    public void init() {
        try {
            //创建NioEventLoopGroup
            nioEventLoopGroup = new NioEventLoopGroup();
            //创建客户端启动助手
            Bootstrap bootstrap = new Bootstrap();
            //设置参数
            bootstrap.group(nioEventLoopGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            //添加编解码器
                            pipeline.addLast(new StringDecoder());
                            pipeline.addLast(new StringEncoder());
                            //todo：添加业务处理器
                            pipeline.addLast(myRpcClientHandler);

                        }
                    });
            //连接服务端
             channel = bootstrap.connect(ip, port).sync().channel();
            System.out.println("============客户端成功连接==="+ip+":"+port+"服务端===========");
        } catch (InterruptedException e) {
            e.printStackTrace();
            if(channel != null){
                channel.close();
            }
            if(nioEventLoopGroup != null){
                nioEventLoopGroup.shutdownGracefully();
            }
        }
    }

    /**
     *
     *功能描述:关闭方法
     * @return void
     * @author zj
     * @date 2021/12/9
     */
    public void close(){
        if(channel != null){
            channel.close();
        }
        if(nioEventLoopGroup != null){
            nioEventLoopGroup.shutdownGracefully();
        }
    }

    /**
     *
     *功能描述:发送消息
     * @return java.lang.Object
     * @author zj
     * @date 2021/12/9
     */
    public Object send(String requestMessage) throws ExecutionException, InterruptedException {
        myRpcClientHandler.setRequestMessage(requestMessage);
        Future submit = executorService.submit(myRpcClientHandler);
        return submit.get();
    }
}
